#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>

typedef char string[256];

//prints the words in <inString> which start with the <inLetter>
void print_letter_words(char* inString,char inLetter);

//returns an address of a string with only leters  
char* only_alpha(char* inString);

//returns 1 if str is palindrom 0 if not
int is_palindrom(char* inString);

//returns an address of the decoding of <inString> code 
char*string_code(char* inString);

//arranges the string in an array of char pointers, every word in a string
char** arrange_string(char *inString,int*inNum);

//counts the number of the varibles in the decleration
int num_of_var(char* inString);

//prints the memory size of the varible 
void print(char** inPointer,int inSize,int inNum);

//returns the memory size of the array
int size_of_array(char* inString);

//return an address of the name of the array 
char*return_name_array(char* inString);

//the main function of the mini compiler which prints the memory size 
void print_memory_size(char* inString);

//free the memory  
void free_ptrarray(char** inPointer,int inSize);

int main() 
{
	int iChoice=0,iLength;
	string sString;
	char *pString;

	printf("****************************************************************\n");
	printf("      Exercise 2			\n");
	printf("							\n");
	printf("      Oren Attia			\n");
	printf("      ID:29074333			\n");
	printf("							\n");
	printf("      Computer Science		\n"); 
	printf("							\n");
	printf("****************************************************************\n");

	while(iChoice!=6)
	{
		printf("\n");
		printf("1. Exercise 1 \n");
		printf("2. Exercise 2 \n");
		printf("3. Exercise 3 \n");
		printf("4. Exercise 4 \n");
		printf("5. Exercise 5 \n");
		printf("6. EXIT\n");
		printf("Enter your choice : ");
		scanf("%d",&iChoice);
		switch(iChoice)
			{
				case 1 :
					{
						printf("Enter a string: ");
						flushall();
						gets(sString);
						printf("Enter a letter: ");
						print_letter_words(sString,getchar());

						printf("\n");

					break;
					}			
				case 2 :
					{
						printf("Enter a string: ");
						flushall();
						gets(sString);
						pString = only_alpha(sString);
						if(pString == NULL)
								printf("Failed to Allocate Memory!!!");
						else
						{
							puts(pString);
							free(pString);
						}
						
						printf("\n");

					break;
					}
				case 3 :
					{
						printf("Enter a string: ");
						flushall();
						gets(sString);
						iLength = strlen(sString);
						pString = sString;
						if(is_palindrom(pString,iLength))
							printf("String is Palindrom!\n");
						else 
							printf("String is not Palindrom !\n");
						
					break;
					}
				case 4 :
					{
						printf("Enter a String Code: ");
						flushall();
						gets(sString);
						pString = string_code(sString);
						if(pString == NULL)
								printf("Failed to Allocate Memory!!!");
						else
						{
							puts(pString);
							free(pString);
							}
					
					break;
					}
				case 5 :
					{
						printf("Enter a Decleration String: ");
						flushall();
						gets(sString);
						pString = sString;
						print_memory_size(pString);
						
					break;
					}
				case 6 :
					exit(0);
				default:
					{
						printf("Invalid choice\n");
						getch();
					break;
					}
			}
		getch();
	}
return 0;
}

//Exercise 1 Functions
void print_letter_words(char* inString,char inLetter)
{
	int i=0;
	if(inString[0]==inLetter || inString[0]==inLetter-32 || inString[0]==inLetter+32)
	{
		while(inString[i] != 32)
		{
			putchar(inString[i]);
			i++;
		}
		putchar(32);
	}
	while(inString[i] != 0)
	{
		if((inString[i]==inLetter || inString[i]==(inLetter-32) || inString[i]==(inLetter+32)) && inString[i-1]==32)
		{
			while(inString[i] != 32 && inString[i] != 0)
				{
					putchar(inString[i]);
					i++;
				}
			putchar(' ');
		}
		else i++;
	}
}
//Exercise 2 Functions
char* only_alpha(char* inString)
{
	int i,j;
	char* tmpString;
	for(i=0,j=0;inString[i] != '\0';i++)
		if(isalpha(inString[i]))
			j++;
	tmpString = malloc((j+1)*sizeof(char));
	if(tmpString == NULL)
			return NULL;
	tmpString[j] = '\0';
	for(i=0,j=0; inString[i] != '\0';i++)
		if(isalpha(inString[i]))
		{
			tmpString[j] = inString[i];
			j++;
		}
		return tmpString;
}
//Exercise 3 Functions
int is_palindrom(char* inString,int inLength)
{
	if(inLength == 1) return 1;
	if(inLength == 2)
		if(inString[0]==inString[1] || inString[0]==(inString[1]-32) || inString[0]==(inString[1]+32)) 
			return 1;
		else
			return 0;
	if(inString[0]==inString[inLength-1] || inString[0]==(inString[inLength-1]-32) || inString[0]==(inString[inLength-1]+32)) 
		return is_palindrom(inString+1,inLength-2);
	else 
		return 0;
}
//Exercise 4 Functions
char* string_code(char* inString)
{
	char* tmpString;
	int i,j,length;

	length = strlen(inString);
	tmpString = malloc((length+1)*sizeof(char));
	if(tmpString == NULL)
			return NULL;
	tmpString[length] = '\0';
	for(i=1,j=1; i <= length;i++)
		if(inString[i-1] == 32)
		{
			tmpString[i-1] = 32;
			j=1;
		}
		else
		{
			tmpString[i-1] = inString[i-1] - j;
			j++;
		}
	return tmpString;

}
//Exercise 5 Functions
int num_of_var(char* inString)
{
	int i;
	for(i=0;*inString != ';';inString++)
		if(*inString == ',')
			i++;
	return i + 1;
}

char** arrange_string(char *inString,int* inNum)
{
	char *tmpPointerD1,**tmpPointerD2;
	int tmpNum;

	*inNum = num_of_var(inString); 
    inString=strchr(inString,32);
	tmpPointerD1=inString + 1;
	putchar('\n');
	tmpPointerD2 = malloc((*inNum)*sizeof(char*));
	for(tmpNum=0;*inString!='\0';inString++)
	{
		if(*inString == ',' || *inString == ';' )
		{
			*inString = '\0';
			tmpPointerD2[tmpNum] = malloc((strlen(tmpPointerD1)+1)*sizeof(char));
			strcpy(tmpPointerD2[tmpNum],tmpPointerD1);
			tmpPointerD1=inString + 1;
			tmpNum++;
		}
	}
	return tmpPointerD2;
}

void print_memory_size(char* inString)
{
	char ch,**ptr;
	int size,i;;
	ch = inString[0];
	ptr = arrange_string(inString,&size);
	switch(ch)
	{
		case 'i':   print(ptr,size,4);
					break;
		case 'd':   print(ptr,size,8);
					break;
		case 'f':	print(ptr,size,4);
					break;
		case 'l':	print(ptr,size,4);
					break;
		case 's':	print(ptr,size,2);
					break;
		case 'c':	print(ptr,size,1);
					break;
		
		default:	printf("ERROR!!! no such type!!!\n");
	}
	free_ptrarray(ptr,size);
}

void print(char**ptr,int size,int m)
{
	int i,j;
	 for(i=0;i<size;i++)
	 {
		 if(ptr[i][0] == '*' && ptr[i][strlen(ptr[i])-1] == ']')
			 printf("%s requires %d bytes.\n",return_name_array(ptr[i]+1),size_of_array(ptr[i])*4);
		
		 else if(ptr[i][0] == '*')
			 printf("%s requires 4 bytes.\n",ptr[i]+1);
		 
		 else if(ptr[i][strlen(ptr[i])-1] == ']')
			 printf("%s requires %d bytes.\n", return_name_array(ptr[i]),size_of_array(ptr[i])*m);
		 
		 else
			 printf("%s requires %d bytes.\n",ptr[i],m);
	 }
}

int size_of_array(char*str)
{
	int i,j=1,x=0;
	i = strlen(str)-2;
			while(str[i]!='[')
			{
				x += (str[i]-48)*j;
				j*=10;
				i--;
			}
		
		return x;
}

char*return_name_array(char*str)
{
	int j,i;
	char*ptr;
	for(j=0;str[j]!='[';j++);
	ptr = malloc((j+1)*sizeof(char));
	ptr[j] = '\0';
	for(i=0;i<j;i++)
		ptr[i] = str[i];
	return ptr;
}

void free_ptrarray(char**ptr,int size)
{
	int i;
	for(i=0;i<size;i++)
		free(ptr[i]);
	free(ptr);
}
